﻿using CSRedis;
using Demo.Net.Infrastructure;
using Demo.Net.JWT.Model;
using Demo.Net.SqlSugar;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

namespace Demo.Net.JWT.Controllers
{
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class AuthController : ControllerBase
    {

        private readonly IConfiguration _configuration;

        private readonly CSRedisClient _redisClient;

        private readonly SqlSugarDBCom _dbCom;

        public AuthController(IConfiguration configuration,IServiceProvider serviceProvider)
        {
            _configuration = configuration;

            _dbCom = serviceProvider.GetRequiredService<SqlSugarDBCom>();

            _redisClient = serviceProvider.GetRequiredService<CSRedisClient>();
        }


        /// <summary>
        /// 登录（配合Redis 做Token刷新）
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
 
        [HttpPost]
        public async Task<IActionResult> Login([FromBody]LoginModel model)
        {
            var user = await _dbCom.Tusr_User.AsQueryable().SingleAsync(p => p.UserName == model.UserName);
            if (user == null)
            {
                return Ok("账号不存在");
            }
            var pwd = SecurityHelper.MD5WithSalt(model.Password, user.PwdSalt);
            if (pwd != user.UserPwd)
            {
                return Ok("密码错误");
            }
            //验证账号密码后,生成Token
            var accessToken=  GenerateAccessToken(user);
            //生成refreshToken ,与用户ID相关联
            var refreshToken = Guid.NewGuid().ToString();
            await _redisClient.SetAsync(refreshToken, user.UserId.ToString(), TimeSpan.FromDays(2));
            return Ok(new
            {
                access_token = accessToken,
                refresh_Token = refreshToken
            });
        }


        /// <summary>
        /// 刷新Token
        /// </summary>
        /// <param name="refreshToken"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IActionResult> RefreshToken(string refreshToken)
        {
            //验证refreshToken
             var userId =await  _redisClient.GetAsync(refreshToken);
            if (userId == null)
            {
                return Ok("需要重新登录");
            }
            var user = await _dbCom.Tusr_User.GetByIdAsync(int.Parse(userId));
            if (user == null)
            {
                return Ok("登录异常，请重新登录");
            }
            //生成新的Token
            var newAccessToken = GenerateAccessToken(user);
            //使原来的RefreshToken令牌失效
            await _redisClient.DelAsync(refreshToken);
            //生成新的refreshToken ,与用户ID相关联
            var newrefreshToken = Guid.NewGuid().ToString();
            await _redisClient.SetAsync(newrefreshToken, user.UserId.ToString(), TimeSpan.FromDays(2));
            return Ok(new
            {
                access_token = newAccessToken,
                refresh_Token = newrefreshToken
            });
        }
        #region 生成Token的方法 

        private string GenerateAccessToken(Tusr_User user) 
        {

            var claims = new[] {
              new Claim( ClaimTypes.NameIdentifier,user.UserId.ToString()),
              new Claim( ClaimTypes.Role,"管理员"),
              new Claim(ClaimTypes.Name,user.UserName),
              new Claim("realname",user.RealName) //自定义的（ClaimsTypes没有的）
            };
            var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:Key"]));
            var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
            var token = new JwtSecurityToken(
               issuer: _configuration["Jwt:Issuer"],
               audience: _configuration["Jwt:Audience"],
               expires: DateTime.Now.AddMinutes(60), //过期时间 1个小时
               signingCredentials: credentials,
              claims: claims
             );
            return new JwtSecurityTokenHandler().WriteToken(token);
        }
        #endregion
    }
}
